package service

import (
	"encoding/json"
	"errors"
	"fmt"
	"gin/baidu"
	client "gin/baidu/bduss"
	"gin/baidu/pcs"
	"gin/baidu/pcs/baidupcs"
	"gin/baidu/pcs/share/pcsconfig"
	"gin/cache"
	Mysql "gin/database"
	"gin/model"
	"gin/validate"
	"github.com/robertkrimen/otto"
	"github.com/spf13/viper"
	teamones_helper "github.com/teamones-open/go-helper"
	"github.com/tebeka/selenium"
	"io/ioutil"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"os"
	"regexp"
	"strings"
	"time"
)

type QrImageData struct {
	ImageUrl string `json:"imgurl"`
	Errno    int64  `json:"errno"`
	Sign     string `json:"sign"`
}

type QueryData struct {
	ChannelV string `json:"channel_v"`
}

type QrCodeLogin struct {
	httpClient *client.HTTPClient
}

func (q *QrCodeLogin) InitClient() {
	q.httpClient = client.NewHTTPClient()
}

func (*QrCodeLogin) GenerateGid() (gid string, err error) {
	vm := otto.New()
	vm.Run(`
        function u(x, K) {
			x += '';
			for (var N = [], T = 0; T < K.length; T++) N[T % 4] ^= K.charCodeAt(T);
			var U = ['EC', 'OK'],
			V = [];
			V[0] = x >> 24 & 255 ^ U[0].charCodeAt(0);
			V[1] = x >> 16 & 255 ^ U[0].charCodeAt(1);
			V[2] = x >> 8 & 255 ^ U[1].charCodeAt(0);
			V[3] = x & 255 ^ U[1].charCodeAt(1);
			U = [];
			for (T = 0; T < 8; T++) U[T] = T % 2 == 0 ? N[T >> 1] : V[T >> 1];
			N = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
			V = '';
			for (T = 0; T < U.length; T++) {
				V += N[U[T] >> 4 & 15];
				V += N[U[T] & 15]
			}
			return V
        }

		function generate_gid() {
			return "xxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(e) {
				var t = 16 * Math.random() | 0
				var n = "x" === e ? t : 3 & t | 8;
				return n.toString(16)
			}).toUpperCase()
		}
        
		//var abc = '1'+'2'

		`)
	//使用vm.Call(函数名,nil,传递的参数,如果后面有多个参数，用逗号隔开就可以了)
	//value, _ := vm.Call("u", nil, "12345678", "234")
	//value, _ := vm.Get("abc")
	var value otto.Value
	value, err = vm.Call("generate_gid", nil)
	if err != nil {
		return
	}
	gid = value.String()
	return
}

func (q *QrCodeLogin) GetQrCode(gid string) (callBack string, respBody []byte, err error) {

	t := int64(time.Now().Unix() * 1000)
	t1 := t + 21232
	t2 := t1 + 4
	callBack = fmt.Sprintf("tangram_guid_%d", t)
	webUrl := fmt.Sprintf("https://passport.baidu.com/v2/api/getqrcode?lp=pc&qrloginfrom=pc&gid=%s&callback=%s&apiver=v3&tt=%d&tpl=netdisk&_=%d", gid, callBack, t1, t2)

	headers := map[string]string{
		"Accept":          "*/*",
		"Accept-Encoding": "gzip, deflate, br",
		"Accept-Language": "en,zh-CN;q=0.9,zh;q=0.8",
		"Connection":      "keep-alive",
		"Host":            "passport.baidu.com",
		"Referer":         "https://pan.baidu.com/",
		"Sec-Fetch-Dest":  "script",
		"Sec-Fetch-Mode":  "no-cors",
		"Sec-Fetch-Site":  "same-site",
		"User-Agent":      "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
	}

	respBody, err = q.httpClient.Fetch(webUrl, http.MethodGet, headers, nil)
	if err != nil {
		return
	}

	return
}

func (q *QrCodeLogin) DownloadQrCode(imageUrl string, fileName string) (qrcodePath string, err error) {

	headers := map[string]string{
		"Accept":          "image/webp,image/apng,image/*,*/*;q=0.8",
		"Accept-Encoding": "gzip, deflate, br",
		"Accept-Language": "en,zh-CN;q=0.9,zh;q=0.8",
		"Connection":      "keep-alive",
		"Host":            "passport.baidu.com",
		"Referer":         "https://pan.baidu.com/",
		"Sec-Fetch-Dest":  "image",
		"Sec-Fetch-Mode":  "no-cors",
		"Sec-Fetch-Site":  "same-site",
		"User-Agent":      "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
	}
	respBody, err := q.httpClient.Fetch(imageUrl, http.MethodGet, headers, nil)
	if err != nil {
		return
	}

	file, err := ioutil.TempFile("", "*.png")
	if err != nil {
		return
	}
	//defer os.Remove(file.Name())

	_, err = file.Write(respBody)
	if err != nil {
		return
	}
	_ = file.Close()
	//fmt.Println("qrcode image file path is:", file.Name())

	qrcodePath = viper.GetString("server.staticPath") + "qrcode/" + fileName + ".png"
	if flag, _ := teamones_helper.PathExists(viper.GetString("server.staticPath") + "qrcode/"); !flag {
		err = teamones_helper.CreateDirectory(viper.GetString("server.staticPath") + "qrcode/")
		if err != nil {
			return
		}
	}

	imageFile, err := os.Create(qrcodePath)
	if err != nil {
		return
	}
	defer imageFile.Close()

	_, _ = imageFile.Write(respBody)

	return
}

func (q *QrCodeLogin) QueryQrCode(channelId string, gid string) (v string, err error) {

	for {

		time.Sleep(2 * time.Second)
		t := time.Now().Unix() * 1000
		callBack := fmt.Sprintf("tangram_guid_%d", t)
		t1 := t + 5
		t2 := t1 + 5

		webUrl := fmt.Sprintf("https://passport.baidu.com/channel/unicast?channel_id=%s&tpl=netdisk&gid=%s&callback=%s&apiver=v3&tt=%d&_=%d", channelId, gid, callBack, t1, t2)
		headers := map[string]string{
			"Accept":          "*/*",
			"Accept-Encoding": "gzip, deflate, br",
			"Accept-Language": "en,zh-CN;q=0.9,zh;q=0.8",
			"Connection":      "keep-alive",
			"Host":            "passport.baidu.com",
			"Referer":         "https://pan.baidu.com/",
			"Sec-Fetch-Dest":  "script",
			"Sec-Fetch-Mode":  "no-cors",
			"Sec-Fetch-Site":  "same-site",
			"User-Agent":      "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
		}

		var respBody []byte
		respBody, err = q.httpClient.Fetch(webUrl, http.MethodGet, headers, nil)
		if err != nil {
			return
		}

		reg := regexp.MustCompile(fmt.Sprintf("%s\\(([\\S]+?)\\)", callBack))
		res := reg.FindAllSubmatch(respBody, -1)

		if len(res) <= 0 {
			return
		}

		respBody = res[0][1]
		d := &QueryData{}

		err = json.Unmarshal(respBody, d)
		if err != nil {
			return
		}

		channelV := d.ChannelV
		var tempMap map[string]interface{}

		err = json.Unmarshal([]byte(channelV), &tempMap)
		if err != nil {
			continue
		}
		var ok bool
		v, ok = tempMap["v"].(string)
		if ok {
			return
		}
	}

	return
}

func (q *QrCodeLogin) parseCallBackData(callBack string, respBody []byte) (parsedBody []byte, err error) {

	if callBack == "" {
		return
	}
	reg := regexp.MustCompile(fmt.Sprintf("%s\\(([\\s\\S]+?)\\)", callBack))
	res := reg.FindAllSubmatch(respBody, -1)

	if len(res) <= 0 {
		err = errors.New("CallBackError")
		return
	}

	parsedBody = res[0][1]
	return
}

func (q *QrCodeLogin) Login(fakeBduss string) (bduss, Stoken, Ptoken, cookiesStr string, err error) {

	t := time.Now().Unix() * 1000
	t1 := t + 225
	callBack := "bd__cbs__ay6xvs"
	webUrl := fmt.Sprintf("https://passport.baidu.com/v3/login/main/qrbdusslogin?v=%d&bduss=%s&loginVersion=v4&qrcode=1&tpl=netdisk&apiver=v3&tt=%d&traceid=&time=%d&alg=v3&callback=%s", t, fakeBduss, t, t1, callBack)
	webUrl = webUrl + "&u=https%253A%252F%252Fpan.baidu.com%252Fdisk%252Fhome"
	headers := map[string]string{
		"Accept":                    "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
		"Accept-Encoding":           "deflate, br",
		"Accept-Language":           "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
		"Cache-Control":             "max-age=0",
		"Connection":                "keep-alive",
		"Host":                      "passport.baidu.com",
		"Sec-Fetch-Dest":            "document",
		"Sec-Fetch-Mode":            "navigate",
		"Sec-Fetch-Site":            "none",
		"Sec-Fetch-User":            "?1",
		"Upgrade-Insecure-Requests": "1",
		"User-Agent":                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66",
	}
	var respBody []byte
	//response,err := q.httpClient.Do()
	req, err := http.NewRequest("GET", webUrl, nil)

	if err != nil {
		return
	}
	for k, v := range headers {
		req.Header.Set(k, v)
	}
	response, err := q.httpClient.Do(req)
	if err != nil {
		return
	}
	respBody, err = ioutil.ReadAll(response.Body)

	//respBody, err = q.httpClient.Fetch(webUrl, http.MethodGet, headers, nil)
	if err != nil {
		return
	}

	respBody, err = q.parseCallBackData(callBack, respBody)
	if err != nil {
		return
	}
	text := string(respBody)
	// "Accept-Encoding":           "deflate, br", 去掉了gzip 解码有点问题
	text = strings.ReplaceAll(text, "'", "\"") // 返回的格式中 'data' 可能是单引号
	text = strings.ReplaceAll(text, " ", "")
	text = strings.ReplaceAll(text, "\\", "")
	d := &LoginData{}
	err = json.Unmarshal([]byte(text), d)
	if err != nil {
		return
	}

	// 只需要bduss的可以下车了
	bduss = d.Data.Session.Bduss
	Stoken = d.Data.Session.Stoken
	Ptoken = d.Data.Session.Ptoken

	q.httpClient.Jar, _ = cookiejar.New(nil)
	cookiesBase := response.Cookies()
	q.httpClient.Jar.SetCookies(req.URL, cookiesBase)

	// 访问disk home  获得csrftoken

	dishomeReq, _ := http.NewRequest("GET", "https://pan.baidu.com/disk/home", nil)
	for _, ck := range response.Cookies() {
		dishomeReq.AddCookie(ck)
		cookiesBase = append(cookiesBase, ck)
	}
	q.httpClient.Jar.SetCookies(dishomeReq.URL, cookiesBase)
	q.httpClient.Transport = http.DefaultTransport
	response, err = q.httpClient.Transport.RoundTrip(dishomeReq)
	if err != nil {
		return
	}

	webUrl = response.Header.Get("Location")
	// 通过passport 去验证登录 获取stoken
	authRequest, _ := http.NewRequest("GET", webUrl, nil)
	// 设置csrftoken cookies
	for _, ck := range response.Cookies() {
		authRequest.AddCookie(ck)
		cookiesBase = append(cookiesBase, ck)
	}
	q.httpClient.Client.Jar.SetCookies(authRequest.URL, cookiesBase)
	response, err = q.httpClient.Transport.RoundTrip(authRequest)

	if err != nil {
		return
	}
	location := response.Header.Get("Location")

	urlInfo, err := url.Parse(location)
	if err != nil {
		return
	}
	println(urlInfo.RawQuery)
	//queryMap, _ := url.ParseQuery(urlInfo.RawQuery)
	//Stoken = queryMap["stoken"][0]

	return
}

type LoginData struct {
	Data SessionData `json:"data"`
}

type SessionData struct {
	Session SessionInfo `json:"session"`
}
type SessionInfo struct {
	Bduss  string `json:"bduss"`
	Stoken string `json:"stoken"`
	Ptoken string `json:"ptoken"`
}

func (q *QrCodeLogin) GetHomePage() {

	webUrl := "https://pan.baidu.com/disk/home"
	headers := map[string]string{
		"Host":                      "pan.baidu.com",
		"Connection":                "keep-alive",
		"Upgrade-Insecure-Requests": "1",
		"User-Agent":                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
		"Accept":                    "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
		"Sec-Fetch-Site":            "same-origin",
		"Sec-Fetch-Mode":            "navigate",
		"Sec-Fetch-Dest":            "document",
		"Referer":                   "https://pan.baidu.com/",
		"Accept-Language":           "en,zh-CN;q=0.9,zh;q=0.8",
	}
	_, err := q.httpClient.Fetch(webUrl, http.MethodGet, headers, nil)
	if err != nil {
		return
	}
}

func (q *QrCodeLogin) GetBdstoken() (bdstoken string, err error) {

	webUrl := "https://tongxunlu.baidu.com"

	respBody, err := q.httpClient.Fetch(webUrl, http.MethodGet, nil, nil)
	if err != nil {
		return
	}

	reg := regexp.MustCompile(`var bdstoken = '(.*?)'`)
	res := reg.FindAllSubmatch(respBody, -1)

	if len(res) > 0 {
		if len(res[0]) > 1 {
			bdstoken = string(res[0][1])
		}
	}
	if bdstoken == "" {
		err = errors.New("bdstoken not found")
	}
	return
}

// GetElementWithRetryTimes 尝试获取网页元素
func GetElementWithRetryTimes(wb *selenium.WebDriver, cssSelector string, maxTimes uint) (element selenium.WebElement, err error) {
	var count uint = 0

	for {
		element, err = (*wb).FindElement(selenium.ByCSSSelector, cssSelector)
		if err != nil {
		}
		if element != nil {
			break
		}
		count += 1
		if count >= maxTimes {
			return
		}
		time.Sleep(1 * time.Second)
	}
	return
}

// CheckLoginState 检查登录状态
func CheckLoginState(wb selenium.WebDriver, maxTimes uint) (element []selenium.Cookie, err error) {
	var count uint = 0

	for {
		currentUrl, err := wb.CurrentURL()
		if err == nil {
			re, _ := regexp.Compile(`(https://pan.baidu.com/disk/home).*`)
			sub := re.FindSubmatch([]byte(currentUrl))

			if len(sub) > 0 {
				element, err = wb.GetCookies()
				break
			}

		} else {
		}
		count += 1
		if count >= maxTimes {
			break
		}
		time.Sleep(500 * time.Millisecond)
	}
	return
}

// GetPcLoginQrCode 获得qrcode url
func GetPcLoginQrCode(wd *selenium.WebDriver, maxTimes uint) (element selenium.WebElement, err error) {
	var count uint = 0
	var qrcodeImg selenium.WebElement
	for {
		imageWrapper, err := GetElementWithRetryTimes(wd, "#TANGRAM__PSP_4__QrcodeMain", 30)
		if err != nil {
			continue
		}
		qrcodeImg, err = imageWrapper.FindElement(selenium.ByCSSSelector, ".tang-pass-qrcode-img")
		if err != nil {
			println(err.Error())
		}
		if qrcodeImg != nil {
			attr, _ := qrcodeImg.GetAttribute("src")

			if attr != "https://passport.bdimg.com/passApi/img/loading.gif" {
				element = qrcodeImg
				break
			}
		}
		count += 1
		if count >= maxTimes {
			break
		}
		time.Sleep(1 * time.Second)
	}
	return
}

// QueryQrCodedLoginCookies 查询二维码登录cookies
func QueryQrCodedLoginCookies(wd *selenium.WebDriver, maxTimes uint, cName string) (cookies []selenium.Cookie, err error) {
	var count uint = 0
	// 设置运行时标识
	cache.CacheHelper.Set("progressing"+cName, "yes", 10*time.Minute)
	defer cache.CacheHelper.Delete("progressing" + cName)
	// 删除退出标识
	defer cache.CacheHelper.Delete("close_" + cName)
	for {
		if cName != "" {
			cv, flag := cache.CacheHelper.Get("close_" + cName)
			if flag && teamones_helper.StrVal(cv) == "yes" {
				err = errors.New("user send exit signal")
				println("close chrome tab")
				break
			}
		}
		currentUrl, err := (*wd).CurrentURL()
		if err == nil {
			re, _ := regexp.Compile(`(https://pan.baidu.com/disk/home).*`)
			sub := re.FindSubmatch([]byte(currentUrl))

			if len(sub) > 0 {
				cookies, err = (*wd).GetCookies()
				break
			}

		} else {
		}
		count += 1
		if count >= maxTimes {
			break
		}
		time.Sleep(2 * time.Second)
	}
	_ = (*wd).Close()
	return
}

// QueryQrCodedLoginCookiesAndSetCacheCookies 查询登录cookies并且缓存下来cookiesStr
func QueryQrCodedLoginCookiesAndSetCacheCookies(wd *selenium.WebDriver, maxTimes uint, cName string) {
	cookies, err := QueryQrCodedLoginCookies(wd, maxTimes, cName)
	if err != nil {
		return
	}
	cookiesStr := ""
	for _, cookie := range cookies {
		cookiesStr += cookie.Name + "=" + cookie.Value + ";"
	}
	cookiesStr = strings.TrimRight(cookiesStr, ";")
	cache.CacheHelper.Set(cName, cookiesStr, 5*time.Hour)
	baiduUserInfo, err := pcs.Login("", "", "", teamones_helper.StrVal(cookiesStr))
	if err == nil && baiduUserInfo != nil {
		panUser := FindPanUserByBaiduName(baiduUserInfo.Name)
		//UpdatePanUserCookiesExpireAt(&panUser, cookiesStr)
		UpdatePanUserCookies(panUser.Id, cookiesStr)
	}
	return
}

// 更新cookies过期时间
func UpdatePanUserCookiesExpireAt(panUser *model.PanUser) {
	if panUser.Id > 0 {
		// stoken 的过期时间是一个月 所以设置cookies的过期时间是一个月
		d := time.Now().AddDate(0, 1, 0)
		Mysql.DB.Model(&model.PanUser{}).Where("id = ?", panUser.Id).Updates(map[string]interface{}{"cookies_expire_at": d.Unix()})
	}
}

// UpdatePanUserCookies 更新cookies
func UpdatePanUserCookies(panUserId uint64, cookiesStr string) {
	d := time.Now().AddDate(0, 1, 0)
	Mysql.DB.Model(&model.PanUser{}).Where("id = ?", panUserId).Updates(map[string]interface{}{"cookies_expire_at": d.Unix(), "cookies": cookiesStr})

}

// TransferShareFile 转存别人分享的文件
func TransferShareFile(share model.PanShare, baiduUserInfo *pcsconfig.Baidu, storageBasePath string, user model.PanUser) (panFiles []model.PanFile, err error) {

	var link string
	var extraCode string
	pcsIn := baiduUserInfo.BaiduPCS()

	// 检查share是否过期
	if share.ExpireAt != 0 && share.ExpireAt <= time.Now().Unix() {
		// 如果过期 自动生成分享链接
		share, err = RegenerateShare(share)
		if err != nil {
			return
		}
	}

	link = share.Link
	extraCode = share.Password

	if link[len(link)-1:] == "/" {
		link = link[0 : len(link)-1]
	}
	featurestrs := strings.Split(link, "/")
	featurestr := featurestrs[len(featurestrs)-1]
	if strings.Contains(featurestr, "init?") {
		featurestr = "1" + strings.Split(featurestr, "=")[1]
	}
	if (len(featurestr) != 8 && len(featurestr) != 23) || featurestr[0:1] != "1" || len(extraCode) != 4 {
		err = errors.New(fmt.Sprintf("%s失败: %s\n", baidupcs.OperationShareFileSavetoLocal, "链接地址或提取码非法"))
		return
	}

	tokens := pcsIn.AccessSharePage(featurestr, true)
	if tokens["ErrMsg"] != "0" {
		err = errors.New(fmt.Sprintf("%s失败: %s\n", baidupcs.OperationShareFileSavetoLocal, tokens["ErrMsg"]))
		return
	}

	var vefiryurl string
	featuremap := make(map[string]string)
	featuremap["surl"] = featurestr[1:]
	featuremap["bdstoken"] = tokens["bdstoken"]
	if extraCode != "none" {

		vefiryurl = pcsIn.GenerateShareQueryURL("verify", featuremap).String()
		res := pcsIn.PostShareQuery(vefiryurl, featurestr[1:], map[string]string{
			"pwd":       extraCode,
			"vcode":     "",
			"vcode_str": "",
		})
		if res["ErrMsg"] != "0" {
			err = errors.New(fmt.Sprintf("%s失败: %s\n", baidupcs.OperationShareFileSavetoLocal, res["ErrMsg"]))
			return
		}
	}
	pcsIn.UpdatePCSCookies(true)

	tokens = pcsIn.AccessSharePage(featurestr, false)
	if tokens["ErrMsg"] != "0" {
		err = errors.New(fmt.Sprintf("%s失败: %s\n", baidupcs.OperationShareFileSavetoLocal, tokens["ErrMsg"]))
		return nil, err
	}
	metaJsonStr := tokens["metajson"]
	transMetas := pcsIn.ExtractShareInfo(metaJsonStr)

	if transMetas["ErrMsg"] != "0" {
		err = errors.New(fmt.Sprintf("%s失败: %s\n", baidupcs.OperationShareFileSavetoLocal, transMetas["ErrMsg"]))
		return
	}
	tmpUniquePath := fmt.Sprintf("%s%s/%d/", storageBasePath, time.Now().Format("2006-06-01"), share.Id)

	if transMetas["item_num"] != "1" {
		transMetas["filename"] += "等文件"
	}
	transMetas["path"] = strings.TrimRight(viper.GetString("bcs.path"), "/") + tmpUniquePath

	pcsIn.Mkdir(transMetas["path"])
	// 提前创建目录
	//_, _ = baidu.Create(user.AccessToken, validate.CreatePanParam{
	//	Path:  transMetas["path"],
	//	Size:  0,
	//	Isdir: 1,
	//	Rtype: 0,
	//})

	transMetas["referer"] = "https://pan.baidu.com/s/" + featurestr
	pcsIn.UpdatePCSCookies(true)

	//fsidStr, _ := json.Marshal(fsidList)
	//transMetas["fs_id"] = string(fsidStr)
	//transMetas["app_id"] = "250528"

	resp := pcsIn.GenerateRequestQuery("POST", transMetas)
	if resp["ErrNo"] != "0" {
		err = errors.New(fmt.Sprintf("%s失败: %s %s\n", baidupcs.OperationShareFileSavetoLocal, resp["ErrMsg"], transMetas["path"]))
		if resp["ErrNo"] == "4" {
			transMetas["shorturl"] = featurestr
			pcsIn.SuperTransfer(transMetas, resp["limit"]) // 试验性功能
		}
		return
	}

	// 直接通过access_token 查询目录下面的所有信息 然后添加到pan_file记录中

	start := 0
	limit := 100
	for {
		// 查询刚刚转存文件目录下的所有文件
		fileList, err := baidu.GetPanFileListAll(user.AccessToken, transMetas["path"], start, limit)

		if err != nil {
			return nil, err
		}
		FsIdList := make([]uint64, len(fileList.List))

		for k, v := range fileList.List {
			FsIdList[k] = v.FsId
		}

		// 查询文件的详细信息
		fileMetaResp, err := baidu.GetFileMetaInfo(user.AccessToken, FsIdList, 0, 1, 0)
		if err != nil {
			return nil, err
		}
		// 添加转存文件信息 到pan_file
		for _, file := range fileMetaResp.List {
			panFile, err := RecordUploadFile(validate.RecordPanFileParam{
				PanUserId:      user.Id,
				FsId:           file.FsId,
				Md5:            file.Md5,
				ServerFilename: file.Path,
				Category:       file.Category,
				Path:           file.Path,
				Size:           file.Size,
				Ctime:          file.ServerCtime,
				Mtime:          file.ServerMtime,
				IsDir:          file.Isdir,
				FromShareId:    share.Id,
			})
			if err != nil {
				return nil, err
			}
			// 追加审核结果
			panFile.DownloadLink = fmt.Sprintf("%s&access_token=%s", file.Dlink, user.AccessToken)
			panFiles = append(panFiles, panFile)
		}

		// 当没有更多了之后 直接跳出循环
		if fileList.HasMore == 0 {
			break
		}
		start += limit
	}

	return
}

// 分享链接 续期
func RegenerateShare(share model.PanShare) (shareNew model.PanShare, err error) {

	shareFiles, err := SelectPanFilesByShareId(share.Id, "")
	if err != nil {
		return
	} else if len(shareFiles) == 0 {
		err = errors.New("can`t found share file,please contact uploader")
		return
	}

	param := validate.GenerateShareUrl{
		PanUserId:    share.PanUserId,
		FileFsIdList: make([]uint64, len(shareFiles)),
	}
	for k, v := range shareFiles {
		param.FileFsIdList[k] = v.FsId
	}

	shareNew, err = GenerateShareUrl(param, 1, share.Id)

	return
}
